package com.ruoyi.wvp.service.impl;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.util.ArrayList;
import java.util.List;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.wvp.domain.AddressUnit;
import com.ruoyi.wvp.domain.SurveillanceEvent;
import com.ruoyi.wvp.entity.CommunityMC;
import com.ruoyi.wvp.entity.HomePageParams;
import com.ruoyi.wvp.entity.Statistics;
import com.ruoyi.wvp.service.IAddressUnitService;
import com.ruoyi.wvp.service.ISurveillanceEventService;
import com.ruoyi.wvp.utils.PermissionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.ruoyi.wvp.mapper.CommunityEventCountMapper;
import com.ruoyi.wvp.domain.CommunityEventCount;
import com.ruoyi.wvp.service.ICommunityEventCountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.enums.DeletedEnum;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * 社区事件统计Service业务层处理
 *
 * @author ruoyi
 * @date 2024-08-25
 */
@Service
@Slf4j
public class CommunityEventCountServiceImpl extends ServiceImpl<CommunityEventCountMapper, CommunityEventCount> implements ICommunityEventCountService {
    @Autowired
    private CommunityEventCountMapper communityEventCountMapper;
    @Autowired
    @Lazy
    private ISurveillanceEventService surveillanceEventService;
    @Autowired
    private IAddressUnitService addressUnitService;

    /**
     * 查询社区事件统计
     *
     * @param id 社区事件统计主键
     * @return 社区事件统计
     */
    @Override
    public CommunityEventCount selectCommunityEventCountById(Long id) {
        return communityEventCountMapper.selectCommunityEventCountById(id);
    }

    /**
     * 查询社区事件统计列表
     *
     * @param communityEventCount 社区事件统计
     * @return 社区事件统计
     */
    @Override
    public List<CommunityEventCount> selectCommunityEventCountList(CommunityEventCount communityEventCount) {
        return communityEventCountMapper.selectCommunityEventCountList(communityEventCount);
    }

    /**
     * 新增社区事件统计
     *
     * @param communityEventCount 社区事件统计
     * @return 结果
     */
    @Override
    public int insertCommunityEventCount(CommunityEventCount communityEventCount) {
        return communityEventCountMapper.insertCommunityEventCount(communityEventCount);
    }

    /**
     * 修改社区事件统计
     *
     * @param communityEventCount 社区事件统计
     * @return 结果
     */
    @Override
    public int updateCommunityEventCount(CommunityEventCount communityEventCount) {
        return communityEventCountMapper.updateCommunityEventCount(communityEventCount);
    }

    /**
     * 批量删除社区事件统计
     *
     * @param ids 需要删除的社区事件统计主键
     * @return 结果
     */
    @Override
    public int deleteCommunityEventCountByIds(Long[] ids) {
        return communityEventCountMapper.deleteCommunityEventCountByIds(ids);
    }

    /**
     * 删除社区事件统计信息
     *
     * @param id 社区事件统计主键
     * @return 结果
     */
    @Override
    public int deleteCommunityEventCountById(Long id) {
        return communityEventCountMapper.deleteCommunityEventCountById(id);
    }


    @Override
    public Page<CommunityEventCount> pageList(Page<CommunityEventCount> page, CommunityEventCount communityEventCount) {
        LambdaQueryWrapper<CommunityEventCount> queryWrapper = getQueryWrapper(communityEventCount);
        String sql = PermissionUtil.getDeptAddressUnitSql(SecurityUtils.getDeptId());
        queryWrapper.inSql(CommunityEventCount::getCommunityCode, sql);
        return page(page, queryWrapper);
    }

    @Override
    public List<CommunityEventCount> listAll(CommunityEventCount communityEventCount, HomePageParams homePageParams) {
        LambdaQueryWrapper<CommunityEventCount> queryWrapper = getQueryWrapper(communityEventCount);
        String sql = PermissionUtil.getDeptAddressUnitSql(SecurityUtils.getDeptId());
        AddressUnit addressUnit = null;
        if (Objects.nonNull(homePageParams.getStreet())) {
            LambdaQueryWrapper<AddressUnit> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AddressUnit::getId, homePageParams.getStreet());
            wrapper.eq(AddressUnit::getStatus, DeletedEnum.NOMAL.getValue());
            addressUnit = addressUnitService.getOne(wrapper);
            if (Objects.nonNull(addressUnit)) {
                wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(AddressUnit::getAncestors, addressUnit.getAncestors() + ',' + addressUnit.getId());
                wrapper.inSql(AddressUnit::getId, sql);
                wrapper.eq(AddressUnit::getStatus, DeletedEnum.NOMAL.getValue());
                List<AddressUnit> addressUnits = addressUnitService.list(wrapper);
                if (CollectionUtils.isEmpty(addressUnits)) {
                    return new ArrayList<>();
                }
                List<String> communityCodes = addressUnits.stream().map(item -> item.getId().toString()).collect(Collectors.toList());
                queryWrapper.in(CommunityEventCount::getCommunityCode, communityCodes);
            }
        } else if (Objects.nonNull(homePageParams.getArea())) {
            LambdaQueryWrapper<AddressUnit> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AddressUnit::getStatus, DeletedEnum.NOMAL.getValue());
            wrapper.eq(AddressUnit::getId, homePageParams.getArea());
            addressUnit = addressUnitService.getOne(wrapper);
            if (Objects.nonNull(addressUnit)) {
                wrapper = new LambdaQueryWrapper<>();
                wrapper.likeRight(AddressUnit::getAncestors, addressUnit.getAncestors() + ',' + addressUnit.getId() + ',');
                wrapper.inSql(AddressUnit::getId, sql);
                wrapper.eq(AddressUnit::getStatus, DeletedEnum.NOMAL.getValue());
                List<AddressUnit> addressUnits = addressUnitService.list(wrapper);
                if (CollectionUtils.isEmpty(addressUnits)) {
                    return new ArrayList<>();
                }
                List<String> communityCodes = addressUnits.stream().map(item -> item.getId().toString()).collect(Collectors.toList());
                queryWrapper.in(CommunityEventCount::getCommunityCode, communityCodes);
            }

        }

        queryWrapper.inSql(CommunityEventCount::getCommunityCode, sql);
        return list(queryWrapper);
    }

    @Override
    public List<CommunityEventCount> listAll(CommunityEventCount communityEventCount) {
        return listAll(communityEventCount, new HomePageParams());
    }

    private LambdaQueryWrapper<CommunityEventCount> getQueryWrapper(CommunityEventCount communityEventCount) {
        LambdaQueryWrapper<CommunityEventCount> queryWrapper = Wrappers.lambdaQuery(CommunityEventCount.class);
//        社区ID
        if (StringUtils.isNotEmpty(communityEventCount.getCommunityCode())) {
            queryWrapper.eq(CommunityEventCount::getCommunityCode, communityEventCount.getCommunityCode());
        }


//        事件数量
        if (Objects.nonNull(communityEventCount.getEventCount())) {
            queryWrapper.eq(CommunityEventCount::getEventCount, communityEventCount.getEventCount());
        }


//        年月 2024-01
        if (StringUtils.isNotEmpty(communityEventCount.getMonth())) {
            queryWrapper.eq(CommunityEventCount::getMonth, communityEventCount.getMonth());
        }


        return queryWrapper;
    }

    @Transactional
    @Override
    public boolean addCommunityEventCount(String communityCode) {
        if (StringUtils.isBlank(communityCode)) {
            return false;
        }
        String month = DateUtils.getYearMonth();
        CommunityEventCount communityEventCount = new CommunityEventCount();
        communityEventCount.setMonth(month);
        communityEventCount.setCommunityCode(communityCode);
        CommunityEventCount one = getCommunityEventCount(communityEventCount);
        if (Objects.nonNull(one)) {
            communityEventCountMapper.updateAddCount(communityCode, month);
            return true;
        }
        synchronized (communityCode.intern()) {
            one = getCommunityEventCount(communityEventCount);
            if (Objects.nonNull(one)) {
                communityEventCountMapper.updateAddCount(communityCode, month);
                return true;
            }
            communityEventCount.setEventCount(1L);
            save(communityEventCount);
        }
        return false;
    }

    @Override
    public void sync() {
        ExecutorService executorService = Executors.newFixedThreadPool(6);
        LambdaQueryWrapper<SurveillanceEvent> queryWrapper = Wrappers.lambdaQuery(SurveillanceEvent.class);

        YearMonth yearMonth = YearMonth.now();
        LocalDate localDate = yearMonth.atDay(1);
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MIN);
        queryWrapper.gt(SurveillanceEvent::getEventBeginTime, localDateTime);
        List<SurveillanceEvent> list = surveillanceEventService.list(queryWrapper);
        for (SurveillanceEvent surveillanceEvent : list) {
            executorService.execute(() -> {
                addCommunityEventCount(surveillanceEvent.getCommunityCode());
            });
        }
    }

    @Override
    public Statistics statistics(HomePageParams homePageParams) {
        String sql = PermissionUtil.getDeptAddressUnitSql(SecurityUtils.getDeptId());
        homePageParams.setSql(sql);
        if(Objects.nonNull(homePageParams.getArea())){
            homePageParams.setAreaStr(homePageParams.getArea().toString());
        }
        if(Objects.nonNull(homePageParams.getStreet())){
            homePageParams.setStreetStr(homePageParams.getStreet().toString());
        }
        Statistics statistics = communityEventCountMapper.statistics(homePageParams);
        List<CommunityMC> communityMMC = communityEventCountMapper.findCommunityMMC(sql, homePageParams.getArea(), homePageParams.getStreet());
        statistics.setCommunityDeviceCounts(communityMMC);

        PageUtils.startPage();
        Page<SurveillanceEvent> page = new Page<SurveillanceEvent>();
        page.setCurrent(1);
        page.setSize(10);
        SurveillanceEvent surveillanceEvent = new SurveillanceEvent();
        if (Objects.nonNull(homePageParams.getArea())) {
            surveillanceEvent.setAreaCode(homePageParams.getArea().toString());
        }
        if (Objects.nonNull(homePageParams.getStreet())) {
            surveillanceEvent.setStreetCode(homePageParams.getStreet().toString());
        }
        Page<SurveillanceEvent> surveillanceEventPage = surveillanceEventService.pageList(page, surveillanceEvent);
        statistics.setEvents(surveillanceEventPage.getRecords());
        return statistics;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public CommunityEventCount getCommunityEventCount(CommunityEventCount communityEventCount) {
        LambdaQueryWrapper<CommunityEventCount> queryWrapper = getQueryWrapper(communityEventCount);
        CommunityEventCount one = getOne(queryWrapper);
        return one;
    }
}
